﻿using System;
using System.Data.Linq;
using System.Transactions;
using CoreLibrary.Service;

namespace CoreLibrary.Sql.Linq {

    public abstract class AbstractLinqSqlService : ServiceBase, IDataLoadOptionsAware {

        /// <summary>
        /// Connection provider is mandatory.
        /// </summary>
        public ILinqConnectionProvider Connection { get; set; }

        /// <summary>
        /// Can be overridden to configure DataLoadOptions.
        /// </summary>
        /// <param name="options"></param>
        public virtual void InitDataLoadOptions(DataLoadOptions options) {

        }

        /// <summary>
        /// Can be overridden. The default implmentation checkes whether ConnectionProvider
        /// has been specified.
        /// </summary>
        protected override void OnInit() {
            Asserts.NotNull(Connection, "DatabaseConnection is not specified.");
        }

        /// <summary>
        /// Can be overridden. The default implementation does nothing.
        /// </summary>
        protected override void OnDestroy() {
        }

        /// <summary>
        /// Can be overridden. The default implementation does nothing.
        /// </summary>
        protected override void OnStart() {
        }

        /// <summary>
        /// Can be overridden. The default implementation does nothing.
        /// </summary>
        protected override void OnStop() {
        }

        public void Execute(Action<DataContext> updateQuery) {
            Connection.ExecuteUpdate(updateQuery);
        }

        public T Execute<T>(Func<DataContext, T> selectQuery) {
            return Connection.ExecuteQuery(selectQuery);
        }

        public T Execute<T>(Func<DataContext, TransactionScope, T> transactionalSelectQuery) {
            return Connection.ExecuteQuey(transactionalSelectQuery);
        }

        public void Execute(Action<DataContext, TransactionScope> transactionalUpdateQuery) {
            Connection.ExecuteUpdate(transactionalUpdateQuery);
        }
        
        public T Execute<T>(ISqlQuery<T> query) {
            return Connection.ExecuteQuery(query);
        }

        public T Execute<T>(ISqlScalar<T> scalar) {
            return Connection.ExecuteScalar(scalar);
        }

        public T Execute<T>(ISqlUpdator<T> updator) {
            return Connection.ExecuteUpdate(updator);
        }
    }
}